#pragma once
#include "Octree.h"
#include <Windows.h>

class PhysicsManager
{
public:
	
	PhysicsManager(float BOX_SIZE, float GRAVITY, int in_numThreads, int in_incsize);
	~PhysicsManager(void);

	int INCSIZE;

	vector<Ball*> _balls; //All of the balls
	Octree* _octree; //The root octree with all the balls
	SYSTEM_INFO sysinfo;

	//Returns a random float from 0 to < 1
	float randomFloat();
	//int ThreadsDoneCount; //This increments and is compared to max number of threads.
	int CalcFrame(float frametime);
	void increaseBalls();
	void decreaseBalls();
	//Syncronization of threads. Once their work is filled, this gets flagged.
	HANDLE * hStartEvents;
	HANDLE * hDoneEvents;
	int * WorkerId;
	//Returns whether two balls are colliding
	bool testBallBallCollision(Ball* b1, Ball* b2);

	//Returns whether a ball and a wall are colliding
	bool testBallWallCollision(Ball* ball, Wall wall);

	//Returns the direction from the origin to the wall
	Vec3f wallDirection(Wall wall);

	//BallBallArray
	vector<BallPair>		* BallBallWorkArray;
	vector<BallWallPair>	* BallWallWorkArray;

	vector<Ball*>			* BallsToMove;

	HANDLE * hStartBallMove;
	HANDLE * hStopBallMove;
	unsigned int NUM_JOBS;
private:
	//No default constructor for you. come back one year.
	//PhysicsManager(void);

	float BOX_SIZE;
	float GRAVITY;

	DWORD * dwThreadIdArray; //BallBall
	HANDLE * hThreadArray;
	
	HANDLE * hBallMoveThread;
	DWORD * dwBallMoveThreadId;
	

	//Create all of the thread Jobs.
	int createThreadJobs();

	//Puts potential ball-ball collisions in potentialCollisions.  It must return
	//all actual collisions, but it need not return only actual collisions.
	void potentialBallBallCollisions(vector<BallPair> &potentialCollisions,
									 vector<Ball*> &balls, Octree* octree);

	//Puts potential ball-wall collisions in potentialCollisions.  It must return
	//all actual collisions, but it need not return only actual collisions.
	void potentialBallWallCollisions(vector<BallWallPair> &potentialCollisions,
									 vector<Ball*> &balls, Octree* octree);

	//Moves all of the balls by their velocity times dt
	void moveBalls(vector<Ball*> &balls, Octree* octree, float dt);

	void applyGravity(vector<Ball*> &balls);


	//Handles all ball-ball collisions
	void handleBallBallCollisions(vector<Ball*> &balls, Octree* octree);



	//Handles all ball-wall collisions
	void handleBallWallCollisions(vector<Ball*> &balls, Octree* octree);

	//Applies gravity and handles all collisions.  Should be called every
	//TIME_BETWEEN_UPDATES seconds.
	void performUpdate(vector<Ball*> &balls, Octree* octree);

	//Advances the state of the balls by t.  timeUntilUpdate is the amount of time
	//until the next call to performUpdate.
	void advance(vector<Ball*> &balls,
				 Octree* octree, float time);

	//Deletes everything.  This should be called when exiting the program.
	void cleanup();



};

